import {BaseEntity} from '../core/BaseEntity';
import {DataTypeUtil, getIdGenerator} from '../common';
import {
  DatabaseManager,
  DEFAULT_COLUMN_TYPE,
  DEFAULT_LOGICAL_DELETED_VALUE,
  DEFAULT_LOGICAL_NOT_DELETED_VALUE
} from '../core/DatabaseManager';
import {
  ColumnInfo,
  FieldFiller,
  FieldFillType,
  ForeignKeyInfo,
  IdGenerationStrategy,
  IndexInfo,
  SQLiteDataType,
  TableInfo
} from "../types";

// 元数据存储
const entityMetadataMap = new Map<Function, EntityMetadata<any>>();

/**
 * 用于存储实体类的元数据
 */
interface EntityMetadata<T> {
  tableName: string;
  primaryKey?: string;
  columns: Record<keyof T, ColumnInfo>;
  indices?: IndexInfo[];
  db: DatabaseManager;
}

/**
 * 获取或创建实体的元数据
 */
function getOrCreateMetadata<T>(target: Function): EntityMetadata<T> {
  if (!entityMetadataMap.has(target)) {
    entityMetadataMap.set(target, {
      tableName: '',
      columns: {},
      indices: [],
      db: null as any as DatabaseManager
    });
  }
  return entityMetadataMap.get(target)!;
}

/**
 * 表装饰器，用于定义数据库表的名称和主键
 *
 * @param name 数据库表名
 * @param options 可选，表配置选项
 * @param options.primaryKey 可选，主键列名，默认为'id'
 * @param options.db 可选，数据库管理器
 *
 * @example
 * ```typescript
 * @Table('users', { primaryKey: 'id', dbName: 'app' })
 * class User extends BaseEntity {
 *   // ...
 * }
 * ```
 */
export function Table(name: string, options?: {
  /**
   * 主键列名，默认为'id'
   */
  primaryKey?: string;

  /**
   * 数据库管理器，用于指定使用哪个数据库
   */
  db?: DatabaseManager;
}) {
  return function (target: any) {
    // 获取或创建元数据
    const metadata = getOrCreateMetadata(target);
    metadata.tableName = name;
    if (options) {
      if (options.primaryKey) {
        metadata.primaryKey = options.primaryKey;
      }
    }

    // 保存数据库名称映射
    const dbM = (options ? options.db : null) || DatabaseManager.getInstanceByName();
    if (!dbM) {
      throw new Error(`未找到数据库管理器实例，请确保在使用服务前已创建对应的数据库管理器`);
    }
    dbM.registerEntity(target);
    metadata.db = dbM;

    // 更新所有列的配置
    updateColumnsConfig(metadata);
  };
}

/**
 * 更新所有列的配置信息
 * 当Table装饰器应用后调用，确保所有列都有正确的配置
 */
function updateColumnsConfig<T>(metadata: EntityMetadata<T>): void {
  if (!metadata.db) return;

  // 获取数据库管理器的主键配置
  const defaultColumnType = metadata.db.getOptions().defaultColumnType || DEFAULT_COLUMN_TYPE;

  // 遍历所有列，更新列配置
  for (const key in metadata.columns) {
    const column = metadata.columns[key];

    // 更新主键配置
    if (column.primaryKey) {
      setColumnConfig(metadata, column);
    }
    // 对于普通列，如果type为默认值，则应用数据库的defaultColumnType
    else if (!column.type || column.type === DEFAULT_COLUMN_TYPE) {
      column.type = defaultColumnType;
    }
  }
}

/**
 * 列装饰器，用于定义实体字段对应的数据库列属性
 *
 * @param options 列配置选项
 * @param options.type 列的数据类型
 * @param options.notNull 是否为NOT NULL约束
 * @param options.unique 是否为UNIQUE约束
 * @param options.default 默认值
 * @param options.foreignKey 外键引用信息
 *
 * @example
 * ```typescript
 * @TableField({ type: 'TEXT', notNull: true, unique: true })
 * username!: string;
 * ```
 */
export function TableField(options?: {
  /**
   * 数据类型，例如'INTEGER', 'TEXT', 'REAL', 'BLOB'等
   */
  type?: SQLiteDataType;

  /**
   * 是否为NOT NULL约束
   */
  notNull?: boolean;

  /**
   * 是否为UNIQUE约束
   */
  unique?: boolean;

  /**
   * 默认值
   */
  default?: any;

  /**
   * 外键引用信息
   */
  foreignKey?: ForeignKeyInfo;
}) {
  return function (target: any, propertyKey: string) {
    const constructor = target.constructor;
    const metadata = getOrCreateMetadata<any>(constructor);

    // 创建列信息
    const columnInfo: ColumnInfo = {
      // 优先使用提供的type，其次是metadata.db的默认值，最后是全局默认值
      type: options?.type || (metadata.db ? metadata.db.getOptions().defaultColumnType : null) || DEFAULT_COLUMN_TYPE
    };

    // 设置可选属性
    if (options) {
      if (options.notNull) {
        columnInfo.notNull = options.notNull;
      }
      if (options.unique) {
        columnInfo.unique = options.unique;
      }
      if (options.default !== undefined) {
        columnInfo.default = options.default;
      }
      if (options.foreignKey) {
        columnInfo.foreignKey = options.foreignKey;
      }
    }

    // 保存列信息
    metadata.columns[propertyKey] = columnInfo;
  };
}

/**
 * 索引装饰器，用于定义表索引
 *
 * @param options 索引配置选项
 * @param options.name 索引名称
 * @param options.columns 索引包含的列名数组
 * @param options.unique 是否为唯一索引
 *
 * @example
 * ```typescript
 * @TableIndex<User>({
 *   name: 'idx_users_email',
 *   columns: ['email'],
 *   unique: true
 * })
 * class User extends BaseEntity {
 *   // ...
 * }
 * ```
 */
export function TableIndex<T>(options: {
  /**
   * 索引名称
   */
  name: string;

  /**
   * 索引包含的列名数组，限定为实体类的属性名
   */
  columns: Array<keyof T & string>;

  /**
   * 是否为唯一索引
   */
  unique?: boolean;
}) {
  return function (target: any) {
    const metadata = getOrCreateMetadata(target);

    // 确保indices存在
    if (!metadata.indices) {
      metadata.indices = [];
    }

    // 创建并添加索引信息
    const indexInfo: IndexInfo = {
      name: options.name,
      columns: options.columns,
    };

    if (options.unique) {
      indexInfo.unique = options.unique;
    }

    metadata.indices.push(indexInfo);
  };
}

/**
 * 设置列配置
 * @param metadata 实体元数据
 * @param columnInfo 列配置信息
 */
function setColumnConfig(metadata: EntityMetadata<any>, columnInfo: ColumnInfo): void {
  if (metadata.db) {
    const dbPrimaryKeyConfig = metadata.db.primaryKeyConfig;
    const idGenerationStrategy = dbPrimaryKeyConfig.idGenerationStrategy || IdGenerationStrategy.AUTO_INCREMENT;
    if (idGenerationStrategy === IdGenerationStrategy.AUTO_INCREMENT) {
      columnInfo.autoIncrement = true;
      columnInfo.type = 'INTEGER';
    } else {
      const idGenerator = getIdGenerator(idGenerationStrategy, dbPrimaryKeyConfig.customIdGenerator);
      columnInfo.type = idGenerator.fieldType();
    }
  }
}

/**
 * 主键装饰器，用于标识当前字段是主键
 *
 * @param generateId 是否使用配置的ID生成策略自动生成ID，默认为true
 *
 * @example
 * ```typescript
 * // 基本使用
 * @TableId()
 * id!: number;
 *
 * // 启用自动生成ID
 * @TableId(true)
 * id!: string;
 * ```
 */
export function TableId(generateId: boolean = true) {
  return function (target: any, propertyKey: string) {
    const constructor = target.constructor;
    const metadata = getOrCreateMetadata<any>(constructor);
    // 创建列信息
    const columnInfo: ColumnInfo = {
      type: 'TEXT',
      generateId: generateId || false,
      primaryKey: true,
      notNull: true
    };

    // 如果metadata.db存在，则获取主键配置
    if (metadata.db) {
      setColumnConfig(metadata, columnInfo);
    } else {
      // 如果metadata.db不存在，使用默认配置
      columnInfo.type = 'INTEGER';
      columnInfo.autoIncrement = true;
    }

    // 设置generateId
    columnInfo.generateId = generateId || false;

    // 保存列信息
    metadata.columns[propertyKey] = columnInfo;

    // 设置表的主键
    if (!metadata.primaryKey) {
      metadata.primaryKey = propertyKey;
    }
  };
}

/**
 * 设置实体类的元数据
 *
 * @param entityClass 实体类
 * @param metadata 实体类的元数据
 */
export function setEntityMetadata<T>(entityClass: Function, metadata: EntityMetadata<T>): void {
  entityMetadataMap.set(entityClass, metadata);
}

/**
 * 获取实体类的元数据
 *
 * @param entityClass 实体类
 * @returns 实体类的元数据
 */
export function getEntityMetadata<T>(entityClass: Function): EntityMetadata<T> | undefined {
  return entityMetadataMap.get(entityClass);
}

// 扩展 BaseEntity 以支持获取表信息
Object.defineProperty(BaseEntity, 'getTableInfo', {
  value: function getTableInfo<T>(): TableInfo<T> {
    const constructor = this;
    const metadata = entityMetadataMap.get(constructor);

    if (!metadata || !metadata.tableName) {
      throw new Error(`实体 ${constructor.name} 缺少 @Table 装饰器`);
    }

    return {
      name: metadata.tableName,
      primaryKey: metadata.primaryKey,
      columns: metadata.columns,
      indices: metadata.indices,
      db: metadata.db
    };
  },
  writable: false,
  configurable: true
});

/**
 * 自动填充装饰器，用于标识需要自动填充的字段
 *
 * @param options 填充配置选项
 * @param options.type 填充类型，默认为INSERT_UPDATE
 * @param options.filler 自定义填充器
 *
 * @example
 * ```typescript
 * @TableFill({ type: FieldFillType.INSERT })
 * createTime!: Date;
 *
 * @TableFill({ filler: new CustomFiller() })
 * updateTime!: Date;
 * ```
 */
export function FieldFill(options: {
  /**
   * 填充类型
   */
  type?: FieldFillType;

  /**
   * 自定义填充器
   */
  filler?: FieldFiller;
} = {}) {
  return function (target: any, propertyKey: string) {
    const constructor = target.constructor;
    const metadata = getOrCreateMetadata<any>(constructor);

    // 确保列信息存在
    if (!metadata.columns[propertyKey]) {
      metadata.columns[propertyKey] = {
        type: (metadata.db ? metadata.db.getOptions().defaultColumnType : null) || DEFAULT_COLUMN_TYPE
      };
    }

    // 设置填充配置
    const columnInfo = metadata.columns[propertyKey];
    columnInfo.fillType = options.type || FieldFillType.INSERT_UPDATE;
    if (options.filler) {
      columnInfo.filler = options.filler;
    }
  };
}

/**
 * 逻辑删除字段装饰器，用于标记实体中用于逻辑删除的字段
 *
 * @param options 逻辑删除配置选项
 * @param options.deletedValue 标记为已删除的值
 * @param options.notDeletedValue 标记为未删除的值
 *
 * @example
 * ```typescript
 * @LogicalDelete({ deletedValue: true, notDeletedValue: false })
 * deleted: boolean = false;
 * ```
 */
export function LogicalDelete(options?: {
  /**
   * 标记为已删除的值
   */
  deletedValue?: any;

  /**
   * 标记为未删除的值
   */
  notDeletedValue?: any;
}) {
  return function (target: any, propertyKey: string) {
    const constructor = target.constructor;
    const metadata = getOrCreateMetadata<any>(constructor);

    // 使用DatabaseManager中定义的默认值
    const defaultDeletedValue = DEFAULT_LOGICAL_DELETED_VALUE;
    const defaultNotDeletedValue = DEFAULT_LOGICAL_NOT_DELETED_VALUE;

    // 准备逻辑删除信息，确保即使没有提供options也有默认值
    const logicalDeleteInfo = {
      deletedValue: defaultDeletedValue,
      notDeletedValue: defaultNotDeletedValue,
      ...(options || {})
    };

    // 确定字段类型
    let fieldType: SQLiteDataType = 'INTEGER';

    // 根据配置的值自动确定字段类型
    if (options) {
      // 使用DataTypeUtils工具类确定类型
      fieldType = DataTypeUtil.getTypeFromValues(options.deletedValue, options.notDeletedValue);
    } else if (metadata.db?.logicalDeleteConfig) {
      // 如果未指定值，尝试从全局配置获取类型
      const config = metadata.db.logicalDeleteConfig;
      // 使用DataTypeUtils工具类确定类型
      fieldType = DataTypeUtil.getTypeFromValues(config.deletedValue, config.notDeletedValue);
    } else {
      // 如果全局没有配置且未提供选项，使用默认值的类型
      fieldType = DataTypeUtil.getTypeFromValues(defaultDeletedValue, defaultNotDeletedValue);
    }

    // 确保列信息存在
    if (!metadata.columns[propertyKey]) {
      metadata.columns[propertyKey] = {
        type: fieldType
      };
    } else {
      // 如果列已存在但未指定类型，设置自动确定的类型
      if (!metadata.columns[propertyKey].type) {
        metadata.columns[propertyKey].type = fieldType;
      }
    }

    // 设置逻辑删除信息
    metadata.columns[propertyKey].logicalDelete = logicalDeleteInfo;

    // 设置默认值 (如果未显式设置)
    if (metadata.columns[propertyKey].default === undefined) {
      // 默认设置为未删除状态
      metadata.columns[propertyKey].default = logicalDeleteInfo.notDeletedValue;
    }
  };
}
